package com.lap.gateway.filter;

import com.lap.framework.constant.Header;
import com.lap.framework.dto.result.Result;
import com.lap.framework.enums.SystemCode;
import com.lap.framework.tools.JsonUtil;
import com.lap.gateway.entity.Security;
import com.lap.gateway.service.PermissionMatcher;
import com.lap.gateway.service.PermissionService;
import com.lap.gateway.tools.Constant;
import com.lap.gateway.tools.GatewayError;
import com.lap.gateway.tools.MonoHolder;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.annotation.Order;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

/**
 *
 *
 * <pre>
 * 授权过滤器,提供用户授权校验
 * 必须在鉴权过滤器后面
 * </pre>
 *
 * @author Shuisheng Lao(劳水生)
 * @version 0.0.1
 */
@Slf4j
@Order(Constant.DEFAULT_ORDER + 10)
@Component
public class AuthorizationFilter implements GlobalFilter {

  @Resource private Security security;
  @Resource private PermissionService permissionService;
  @Resource private PermissionMatcher permissionMatcher;

  @Override
  public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
    ServerHttpRequest request = exchange.getRequest();
    String uri = request.getURI().getPath();
    String method = request.getMethod().name();
    if (security.ignoreAuthor(uri, method)) {
      return chain.filter(exchange);
    }

    return permissionService
        .getPermission(
            request.getHeaders().getFirst(Header.USER_ID),
            request.getHeaders().getFirst(Header.USER_NAME),
            request.getHeaders().getFirst(Header.FULL_NAME))
        .flatMap(
            result -> {
              if (SystemCode.failure(result.getCode())) {
                return MonoHolder.onError(exchange.getResponse(), result);
              }

              // TODO
              log.info("获取数据权限:{}", JsonUtil.prettyOut(result));

              return permissionMatcher
                  .match(result.getData().getApiList(), uri, method)
                  .map(api -> chain.filter(exchange))
                  .orElseGet(
                      () -> {
                        String message = String.format("%s: %s unauthorized", method, uri);
                        return MonoHolder.onError(
                            exchange.getResponse(),
                            Result.fail(GatewayError.UNAUTHORIZED, message));
                      });
            });
  }
}
